package com.ruoyi.bussine.service.integration.impl;

import cn.hutool.json.JSONUtil;
import com.ruoyi.bussine.domain.dto.wechat.miniPay.WechatPayReqDTO;
import com.ruoyi.bussine.service.common.ModuleConfigService;
import com.ruoyi.bussine.service.integration.WeChatPayService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.Status;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 商户号：1712582313
 * 密钥key（未使用）：XdLiK206K1JOHkjbhfYH0742HFome0oO
 * <p>
 * 微信文档：https://github.com/wechatpay-apiv3/wechatpay-java
 * 接入示例：https://zhuanlan.zhihu.com/p/709168444
 *
 * @author zhengyz
 * @date 2025/3/21
 * @description 微信支付服务
 */
@Slf4j
@Service
public class WeChatPayServiceImpl implements WeChatPayService {

    /**
     * 商户号
     */
    public static String merchantId = "1712582313";
    /**
     * 商户API私钥路径
     */
    public static String privateKeyPath = "/app/wechatPay/apiclient_key.pem";
    /**
     * 商户证书序列号
     */
    public static String merchantSerialNumber = "56D1B83AB4A73BD42CE21A11747A12D65505F51D";
    /**
     * 商户APIV3密钥
     */
    public static String apiV3Key = "EloKjht6290YUhvPK20615jgFGRpcaHn";
    public static String publicKeyPath = "/app/wechatPay/apiclient_cert.pem";
    // 这个是示例数据
    public static String publicKeyId = "5157F09EFDC096DE15EBE81A47057A72********";

    public static String wechatPayCertificatePath = "/app/wechatPay/wechatpay_3ACC4FCC3D3AEF94E979B6AA8283904F8279B323.pem";

    @Autowired
    private ModuleConfigService moduleConfigService;

    private Config configBuilder() {
        // 使用微信支付公钥的RSA配置，定时更新平台证书配置
        /*return new RSAPublicKeyConfig.Builder()
                        .merchantId(merchantId)
                        .privateKeyFromPath(privateKeyPath)
                        .publicKeyFromPath(publicKeyPath)
                        .publicKeyId(publicKeyId)
                        .merchantSerialNumber(merchantSerialNumber)
                        .apiV3Key(apiV3Key)
                        .build();*/
        // 本地的微信支付平台证书
        /*return new RSAConfig.Builder()
                // 商户号
                .merchantId(merchantId)
                // 商户API私钥
                .privateKeyFromPath(privateKeyPath)
                // 商户证书序列号
                .merchantSerialNumber(merchantSerialNumber)
                // 微信支付平台证书
                .wechatPayCertificatesFromPath(wechatPayCertificatePath)
                .build();*/
        return new RSAConfig.Builder()
                // 商户号
                .merchantId(moduleConfigService.getWxMchId())
                // 商户API私钥
                .privateKeyFromPath(moduleConfigService.getWxPrivateKeyPath())
                // 商户证书序列号
                .merchantSerialNumber(moduleConfigService.getWxMchSerialNo())
                // 微信支付平台证书
                .wechatPayCertificatesFromPath(moduleConfigService.getWxCertificatePath())
                .build();
    }

    @Override
    public PrepayWithRequestPaymentResponse initMiniProgramPay(WechatPayReqDTO wechatPayReqDTO) {
        log.info("initMiniProgramPay.wechatPayReqDTO={}", JSONUtil.toJsonStr(wechatPayReqDTO));
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(configBuilder()).build();

        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(wechatPayReqDTO.getAmount().getTotal());
        Payer payer = new Payer();
        payer.setOpenid(wechatPayReqDTO.getPayer().getOpenid());
        request.setAmount(amount);
        request.setAppid(wechatPayReqDTO.getAppid());
        request.setMchid(wechatPayReqDTO.getMchid());
        request.setDescription(wechatPayReqDTO.getDescription());
        request.setNotifyUrl(wechatPayReqDTO.getNotify_url());
        request.setOutTradeNo(wechatPayReqDTO.getOut_trade_no());
        request.setPayer(payer);
        // response包含了调起支付所需的所有参数，可直接用于前端调起支付
        log.info("initMiniProgramPay.request={}", JSONUtil.toJsonStr(request));
        PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
        log.info("initMiniProgramPay.response={}", JSONUtil.toJsonStr(response));
        return response;
    }

    @Override
    public Transaction queryPayResult(String wxPayNo) {
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(configBuilder()).build();

        QueryOrderByIdRequest queryRequest = new QueryOrderByIdRequest();
        queryRequest.setMchid(moduleConfigService.getWxMchId());
        queryRequest.setTransactionId(wxPayNo);
        Transaction result = null;
        try {
            log.info("queryPayResult.queryRequest={}", JSONUtil.toJsonStr(queryRequest));
            result = service.queryOrderById(queryRequest);
            log.info("queryPayResult.transaction={}", JSONUtil.toJsonStr(result));
        } catch (Exception e) {
            // API返回失败, 例如ORDER_NOT_EXISTS
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public String closeOrder(String orderNo) {
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(configBuilder()).build();

        CloseOrderRequest queryRequest = new CloseOrderRequest();
        queryRequest.setMchid(moduleConfigService.getWxMchId());
        queryRequest.setOutTradeNo(orderNo);
        try {
            log.info("closeOrder.queryRequest={}", JSONUtil.toJsonStr(queryRequest));
            service.closeOrder(queryRequest);
        } catch (Exception e) {
            // API返回失败, 例如ORDER_NOT_EXISTS
            e.printStackTrace();
            return e.getMessage();
        }
        return "";
    }

    @Override
    public Transaction queryPayResultByOrderNo(String orderNo) {
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(configBuilder()).build();

        QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
        queryRequest.setMchid(moduleConfigService.getWxMchId());
        queryRequest.setOutTradeNo(orderNo);
        Transaction result = null;
        try {
            log.info("queryPayResultByOrderNo.queryRequest={}", JSONUtil.toJsonStr(queryRequest));
            result = service.queryOrderByOutTradeNo(queryRequest);
            log.info("queryPayResultByOrderNo.transaction={}", JSONUtil.toJsonStr(result));
        } catch (Exception e) {
            // API返回失败, 例如ORDER_NOT_EXISTS
            e.printStackTrace();
        }
        return result;
    }


    @Override
    public Transaction callbackReply(RequestParam requestParam) {
        NotificationConfig config = new RSAAutoCertificateConfig.Builder()
                .merchantId(moduleConfigService.getWxMchId())
                .privateKeyFromPath(moduleConfigService.getWxPrivateKeyPath())
                .merchantSerialNumber(moduleConfigService.getWxMchSerialNo())
                .apiV3Key(moduleConfigService.getWxApiV3Key())
                .build();
        // 初始化 NotificationParser
        NotificationParser parser = new NotificationParser(config);
        Transaction transaction = null;
        try {
            // 以支付通知回调为例，验签、解密并转换成 Transaction
            log.info("callbackReply.requestParam={}", JSONUtil.toJsonStr(requestParam));
            transaction = parser.parse(requestParam, Transaction.class);
            log.info("callbackReply.transaction={}", JSONUtil.toJsonStr(transaction));
        } catch (Exception e) {
            // 签名验证失败，返回 401 UNAUTHORIZED 状态码
            log.error("sign verification failed", e);
        }
        return transaction;
    }

    @Override
    public Refund refund(CreateRequest refundRequest) {
        RefundService refundService = new RefundService.Builder().config(configBuilder()).build();
        log.info("refund.refundRequest={}", JSONUtil.toJsonStr(refundRequest));
        Refund refundResult;
        try {
            refundResult = refundService.create(refundRequest);
        } catch (Exception e) {
            // API返回失败, 例如ORDER_NOT_EXISTS
            e.printStackTrace();
            refundResult = new Refund();
            refundResult.setStatus(Status.ABNORMAL);
            refundResult.setUserReceivedAccount(e.getMessage());
        }
        log.info("refund.refundRespond={}", JSONUtil.toJsonStr(refundResult));
        return refundResult;
    }

    @Override
    public Refund refundQuery(String refundNo) {
        RefundService refundService = new RefundService.Builder().config(configBuilder()).build();
        QueryByOutRefundNoRequest query = new QueryByOutRefundNoRequest();
        query.setOutRefundNo(refundNo);
        query.setSubMchid(moduleConfigService.getWxMchId());
        log.info("refundQuery.query={}", JSONUtil.toJsonStr(query));
        Refund refund = refundService.queryByOutRefundNo(query);
        log.info("refundQuery.refund={}", JSONUtil.toJsonStr(refund));
        return refund;
    }


}
